import type { ICustomRequestOptions, IResult } from '@/types/common'
import { buildFullURL } from './url'
import { Toast } from './toast'

/**
 * 网络请求封装
 * @see https://blog.csdn.net/weixin_44001222/article/details/138034453
 * @param path 路径
 * @returns
 */

// 添加拦截器
const httpInterceptor = {
  // 拦截前触发
  invoke(options: ICustomRequestOptions) {
    // 默认get
    // @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing
    options.method = options.method ?? 'GET'

    // 通用方法增加userId
    const data = (options.data as AnyObject) ?? {}
    data.userId = getApp().globalData?.userId
    options.data = data

    // 请求超时
    options.timeout = import.meta.env.VITE_APP_TIMEOUT
    options.header = {
      ...options.header
    }

    // 携带 token 授权
    if (options.withToken) {
      options.header = {
        ...options.header,
        Authorization: 'Bearer ' + getApp().globalData!.token
      }
    }

    // 添加 token 请求头标识
    // 判读是否需要显示加载框
    if (options.showloading ?? false) {
      uni.showLoading({
        title: options.loadingText ?? '',
        mask: true
      })
    }
  }
}

uni.addInterceptor('request', httpInterceptor)

export function request<T>(path: string, ops?: ICustomRequestOptions) {
  return new Promise<IResult<T>>((resolve, reject) => {
    uni.request({
      ...(ops as UniApp.RequestOptions),
      url: buildFullURL(import.meta.env.VITE_API_BASEURL, path),
      success: (res) => {
        // 如果开启的加载动画，则隐藏动画
        if (ops?.showloading ?? false) {
          uni.hideLoading()
        }

        const data = res.data as IResult<T>
        // 判断当前的回执码是否正常, 401 说明是登录已经失效了，应该主动退出
        if (data.code == '401') {
          // 存储路由
          handleStorePrevPage()

          // 退出登录
          handleLogoutService()

          // 弹窗提示
          return Toast('请先登录...', function () {
            uni.redirectTo({ url: '/subPages/authorization/index' })
          })
        }
        // 业务失败回执
        else if (data.code != '200') {
          // 显示错误弹窗
          if (ops?.showError ?? true) {
            uni.showToast({
              title: data.msg as string,
              icon: 'none',
              mask: true
            })
          }
          reject(data)
        } else {
          resolve(data)
        }
      },
      fail: (err: any) => {
        if (ops?.showloading ?? false) {
          uni.hideLoading()
        }
        // 显示错误弹窗
        if (ops?.showError ?? true) {
          uni.showToast({
            title: err as string,
            icon: 'none',
            mask: true
          })
        }

        // 返回错误
        const errResult: IResult<T> = {
          code: 500,
          msg: err as string,
          data: null
        }
        reject(errResult)
      }
    })
  })
}
